package com.hilihili.service.impl;

import cn.hutool.json.JSONUtil;
import com.hilihili.config.TranscodeConfig;
import com.hilihili.constant.RedisVideoConstant;
import com.hilihili.domain.dto.*;
import com.hilihili.domain.entity.*;
import com.hilihili.domain.vo.VideoIndexVO;
import com.hilihili.domain.vo.VideoVO;
import com.hilihili.domain.vo.ViewCounts;
import com.hilihili.mapper.UserCoinsMapper;
import com.hilihili.mapper.UserLikeMapper;
import com.hilihili.mapper.VideoMapper;
import com.hilihili.mq.message.VideoTranscodeMessage;
import com.hilihili.mq.service.RabbitMqService;
import com.hilihili.service.ICommentService;
import com.hilihili.service.IDanmakuService;
import com.hilihili.service.IDistrictService;
import com.hilihili.service.IVideoService;
import com.hilihili.transcode.FFmpegUtils;
import com.hilihili.util.DataFormatUtil;
import com.hilihili.util.DateChangeUtil;
import com.hilihili.util.IdWorker;
import com.hilihili.util.VideoType;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.system.service.ISysUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.xml.bind.DatatypeConverter;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 视频Service业务层处理
 *
 * @author xhc
 * @date 2023-11-15
 */
@Slf4j
@Service
public class VideoServiceImpl implements IVideoService {
    @Autowired
    private VideoMapper videoMapper;
    @Autowired
    private ICommentService commentService;
    @Autowired
    private IDanmakuService danmakuService;
    @Autowired
    private ISysUserService iSysUserService;
    @Autowired
    StringRedisTemplate stringRedisTemplate;
    @Autowired
    RedisTemplate<String, Object> objectRedisTemplate;
    @Autowired
    private UserLikeMapper userLikeMapper;
    @Autowired
    private UserCoinsMapper userCoinsMapper;
    @Autowired
    IDistrictService districtService;
    @Autowired
    RabbitMqService videoTranscodingMqServiceImpl;

    @Autowired
    IdWorker idWorker;
    @Autowired
    TranscodeConfig transcodeConfig;


    private Path tempDir = Paths.get(System.getProperty("java.io.tmpdir"));

    /**
     * 更新视频的点赞数
     *
     * @param video id：视频id ,isAdd：true:加1 false:减1
     * @return
     */
    @Override
    @Transactional
    public AjaxResult updateLikesAndChangeTriplet(Video video) {
        // id：视频id ,isAdd：true:加1 false:减1
        // 获取当前用户id
        Long userId = SecurityUtils.getUserId();
        if (userId == null) {
            return AjaxResult.error(401, "未登录");
        }
        UserLike userLike = new UserLike();
        userLike.setUserId(userId);
        userLike.setAlike(video.getId());
        if (video.getIsAdd()) {
            int i = videoMapper.updateLikesAdd(video.getId());
            if (i == 0) {
                return AjaxResult.error();
            }
            // 新增
            userLike.setCreateTime(new Date());
            userLikeMapper.insertUserLike(userLike);
            return AjaxResult.success();
        } else {
            int i = videoMapper.updateLikesSubtract(video.getId());
            if (i == 0) {
                return AjaxResult.error();
            }
            // 删除
            userLikeMapper.deleteUserLikeByUserIdAndAlike(userLike);
            return AjaxResult.success();
        }
    }

    /**
     * 更新视频的投币数
     *
     * @param video id：视频id ,isAdd：true:加1 false:减1
     * @return
     */
    @Override
    @Transactional
    public AjaxResult updateCoinsAndChangeTriplet(Video video) {
        // id：视频id ,isAdd：true:加1 false:减1
        // 获取当前用户id
        Long userId = SecurityUtils.getUserId();
        if (userId == null) {
            return AjaxResult.error(401, "未登录");
        }
        UserCoins userCoins = new UserCoins();
        userCoins.setUserId(userId);
        userCoins.setVideoId(video.getId());
        userCoins.setCoins(video.getCoins());
        if (video.getIsAdd()) {
            int i = videoMapper.updateCoinsSubtract(video.getId(), video.getCoins());
            if (i == 0) {
                return AjaxResult.error();
            }
            // 新增
            userCoins.setCreateTime(new Date());
            userCoinsMapper.insertUserCoins(userCoins);
            return AjaxResult.success();
        } else {
            int i = videoMapper.updateCoinsSubtract(video.getId(), video.getCoins());
            if (i == 0) {
                return AjaxResult.error();
            }
            // 删除
            int i1 = userCoinsMapper.deleteUserCoinsByUserIdAndAlike(userCoins);
            return AjaxResult.success();
        }
    }

    /**
     * 查询视频
     *
     * @param id 视频主键
     * @return 视频
     */
    @Override
    public ResponseEntity selectVideoById(Long id) {
        Video video = videoMapper.selectVideoById(id);
        if (video == null) {
            return ResponseEntity.status(402).body(AjaxResult.error(402, "视频不存在"));
        }
        if (VideoType.COLLECTION.equals(video.getTypeId())) {
            getCollectionVideo(video);
        }
        if (VideoType.EPISODE.equals(video.getTypeId())) {
            getEpisodeVideo(video);
        }
        if (VideoType.THEME.equals(video.getTypeId())) {
            getThemeVideo(video);
        }
        String topic = districtService.getTopicByVideoId(id);
        List<String> tags = districtService.getTagByVideoId(id);
        video.setTopic(topic);
        video.setTags(tags);
        SysUser sysUser = iSysUserService.selectUserById(video.getUp());
        // 设置其他值
        video.setCoinsChange(DataFormatUtil.numChange(video.getCoins()));
        Long commentCount = commentService.selectCommentCountByVideoId(video.getId());
        video.setCommentCount(DataFormatUtil.numChange(commentCount));
        Long danmakuCount = danmakuService.selectDanmakuCountByVideoId(video.getId());
        video.setDanmakuCount(DataFormatUtil.numChange(danmakuCount));
        video.setLikesChange(DataFormatUtil.numChange(video.getLikes()));
        video.setSharesChange(DataFormatUtil.numChange(video.getShares()));
        video.setStarsChange(DataFormatUtil.numChange(video.getStars()));
        Long views = getViewsByVideoId(video.getId().toString());
        video.setViewsChange(DataFormatUtil.numChange(views == -1L ? video.getViews() : views));
        video.setNickname(sysUser.getNickName());
        // 设置up信息
        video.setAvatar(sysUser.getAvatar());
        video.setFollowsChange(DataFormatUtil.numChange(sysUser.getFollows()));
        video.setFansChange(DataFormatUtil.numChange(sysUser.getFans()));
        video.setUpinrtoduction(sysUser.getIntroduction());
        video.setLevel(sysUser.getLevel());
        video.setExperience(sysUser.getExperience());
        return ResponseEntity.status(200).body(AjaxResult.success(video));
    }

    /**
     * 获取主题视频的所有视频
     *
     * @param video
     * @return {@link Video}
     */
    private void getThemeVideo(Video video) {
        List<String> captionIds = videoMapper.selectThemeVideoCaptionId(video.getId());
        if (captionIds.isEmpty()) {
            captionIds = videoMapper.selectThemeVideoCaptionIdByHeadId(video.getId());
        }
        List<CaptionThemeVideoItem> videoItems = new ArrayList<>();
        captionIds.forEach(captionId -> {
            CaptionThemeVideoItem captionThemeVideoItem = new CaptionThemeVideoItem();
            ArrayList<ThemeVideoItem> themeVideoItems = videoMapper.selectThemeVideoItemByCaptionId(Long.parseLong(captionId));
            captionThemeVideoItem.setCaptionId(Long.parseLong(captionId));
            captionThemeVideoItem.setTitle(themeVideoItems.get(0).getTitle());
            captionThemeVideoItem.setItems(themeVideoItems);
            videoItems.add(captionThemeVideoItem);
        });
        video.setVideoItems(videoItems);
    }


    /**
     * 获取合集视频的所有视频
     *
     * @param video
     * @return {@link Video}
     */
    private Video getCollectionVideo(Video video) {
        //如果videoId是首地址 则直接查出返回
        List<CollectionVideoItem> videoItems = videoMapper.selectCollectionVideoItemById(video.getId());
        //如果不是 通过videoId 查找出head_id
        if (videoItems.isEmpty()) {
            videoItems = videoMapper.selectCollectionVideoItemByHeadId(video.getId());
        }
        video.setVideoItems(videoItems);
        video.setIndex(videoMapper.getCollectiomVideoIndex(video.getId()));
        return video;
    }


    /**
     * 剧集视频下的所有视频
     *
     * @param video
     * @return {@link Video}
     */
    private Video getEpisodeVideo(Video video) {
        //如果videoId是首地址 则直接查出返回
        List<EpisodeVideoItem> videoItems = videoMapper.selectEpisodeVideoItemById(video.getId());
        //如果不是 通过videoId 查找出head_id
        if (videoItems.isEmpty()) {
            videoItems = videoMapper.selectEpisodeVideoItemByHeadId(video.getId());
        }
        video.setVideoItems(videoItems);
        video.setIndex(videoMapper.getEpisodeVideoIndex(video.getId()));
        return video;
    }

    /**
     * 查询视频列表
     *
     * @param pageDTO 视频
     * @return 视频
     */
    @Override
    public AjaxResult selectVideoList(PageDTO pageDTO) throws IOException, ClassNotFoundException {
        Random random = new Random();
        List<String> ids = videoMapper.selectVideoIdList(pageDTO);
        ValueOperations opsForValue = stringRedisTemplate.opsForValue();
        List<String> videos = opsForValue.multiGet(ids.stream().map(i -> RedisVideoConstant.VIDEO_INDEX_INFO + i).collect(Collectors.toList()));
        List<VideoIndexVO> videoIndexVOList = new ArrayList<>(ids.size());
        for (int i = 0; i < ids.size(); i++) {
            if (videos == null) {
                videos = new ArrayList<>();
            }
            Object videoStr = videos.get(i);
            // 查询缓存
            if (videos.isEmpty() || videoStr == null) {
                //无缓存
                VideoIndexVO videoIndexVO = videoMapper.selectVideoSimpleInfoById(Long.parseLong(ids.get(i)));
                // 填充前端所需信息
                Long views = getViewsByVideoId(videoIndexVO.getId().toString());
                videoIndexVO.setViewsChange(DataFormatUtil.numChange(views == -1L ? Long.parseLong(videoIndexVO.getViews()) : views));
                // 弹幕
                videoIndexVO.setDanmakuCount(DataFormatUtil.numChange(Long.parseLong(videoIndexVO.getDanmakuCount())));
                // 设置日期
                videoIndexVO.setCreateChange(DateChangeUtil.dateChange(videoIndexVO.getPublishTime()));
                String key = RedisVideoConstant.VIDEO_INDEX_INFO + ids.get(i);
                videoIndexVOList.add(videoIndexVO);
                //保存到redis
                opsForValue.set(key, JSONUtil.toJsonStr(videoIndexVO));
                //设置过期时间 加随机值 防止缓存雪崩
                int anInt = random.nextInt(6);
                stringRedisTemplate.expire(key, 10L + anInt, TimeUnit.SECONDS);
            } else {
                videoIndexVOList.add(JSONUtil.toBean(videos.get(i), VideoIndexVO.class));
            }
        }
        if (videoIndexVOList.isEmpty()) {
            return AjaxResult.error(188, "视频已经见底了");
        }
        return AjaxResult.success(videoIndexVOList);

    }

    /**
     * 新增视频
     *
     * @param video 视频
     * @return 结果
     */
    @Override
    public int insertVideo(Video video) {
        return videoMapper.insertVideo(video);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult insertVideo(VideoSubmitDTO videoSubmitDTO) throws IOException {

        Video video = new Video();
        String fixedDate = videoSubmitDTO.getFixedDate();
        String fixedTime = videoSubmitDTO.getFixedTime();
        String videoId = videoSubmitDTO.getId();
        String upId = videoSubmitDTO.getUp();
        Integer duration = videoSubmitDTO.getDuration();
        String[] district = videoSubmitDTO.getDistrict();
        String transferAddress = videoSubmitDTO.getTransferAddress();
        Topic topic = videoSubmitDTO.getTopic();
        List<Tag> tag = videoSubmitDTO.getTag();
        String introduction = videoSubmitDTO.getIntroduction();
        //视频上传表单校验
        if (videoId == null || videoId.isEmpty()) {
            return AjaxResult.error(500, "请先上传文件！");
        }
        if (upId == null || upId.isEmpty()) {
            return AjaxResult.error(500, "非法请求参数");
        }
        if (duration == null) {
            return AjaxResult.error(500, "网络异常");
        }
        if (district == null || district.length == 0) {
            return AjaxResult.error(500, "请选择视频分区");
        }
        if (topic == null) {
            return AjaxResult.error(500, "请至少选择一个话题！");
        }
        if ("2".equals(videoSubmitDTO.getIsTransfer())) {
            if (transferAddress == null || transferAddress.isEmpty()) {
                return AjaxResult.error(500, "转发来源未填写！");
            }
            video.setTransferAddress(transferAddress);
        }
        if (tag == null || tag.isEmpty()) {
            return AjaxResult.error(500, "请至少选择一个标签！");
        }
        if (introduction == null || introduction.isEmpty()) {
            return AjaxResult.error(500, "视频详情不能为空");
        }
        video.setUpinrtoduction("");
        video.setId(Long.parseLong(videoId));
        video.setUp(Long.parseLong(upId));
        video.setDuration(DateChangeUtil.formatDate(duration));
        video.setViews(0L);
        video.setLikes(0L);
        video.setStars(0L);
        video.setShares(0L);
        video.setCoins(0L);
        video.setCreatedAt(new Date());
        video.setUpdatedAt(new Date());
        String jsonStr = JSONUtil.toJsonStr(district);
        video.setDistrict(jsonStr);
        video.setPromotion(videoSubmitDTO.isPromotion() ? 1 : 0);
        video.setSecondCreation(videoSubmitDTO.isSecondCreated() ? 1 : 0);
        video.setOriginal(videoSubmitDTO.isOriginal() ? 1 : 0);
        //是否设置定时发送
        boolean timing = false;
        if (fixedDate == null || fixedTime == null) {
            //无设置 直接发布
            video.setIsPublish(0);
            video.setPublishTime(new Date());
        } else {
            timing = true;
            //设置则插入定时发布队列
            String date = fixedDate.split("T")[0];
            String publishTime = date + " " + fixedTime;
            videoMapper.insertPublishList(videoId, publishTime);
            video.setIsPublish(0);
        }
        videoMapper.insertVideoTopic(videoId, videoSubmitDTO.getTopic().getValue());
        videoMapper.insertVideoTag(videoId, tag);
        BeanUtils.copyProperties(videoSubmitDTO, video);
        //查看文件是否上传过
        String videoMD5 = videoSubmitDTO.getVideoMD5();
        VideoMD5 md5 = videoMapper.getVideoByMD5(videoMD5);
        if (md5.getVideoId().equals(videoId)) {
            // 将转码信息发送到mq 如已在服务器则不需要转码直接使用第一次转码的地址即可
            Path tempFile = tempDir.resolve(videoId);
            String currentDateTime = DateChangeUtil.getCurrentDateTime();
            Path targetFolder = Files.createDirectories(Paths.get(transcodeConfig.getSource(), currentDateTime, videoId));
            String fileType = videoSubmitDTO.getFileType();
            if (fileType == null || fileType.isEmpty()) {
                return AjaxResult.error("系统异常");
            }
            String filePath = String.join("/", "", currentDateTime, videoId, "index.m3u8");
            videoTranscodingMqServiceImpl.sendMessage(new VideoTranscodeMessage(tempFile.toString(), targetFolder.toString(), videoId, timing, videoMD5, filePath), fileType);
        }else {
            video.setIsPublish(1);
        }
        videoMapper.uploadVideo(video);
        return AjaxResult.success("上传成功");
    }

    @Override
    public List<Video> selectAll() {
        return videoMapper.selectAll();
    }

    /**
     * 修改视频
     *
     * @param video 视频
     * @return 结果
     */
    @Override
    public int updateVideo(Video video) {
        return videoMapper.updateVideo(video);
    }

    /**
     * 批量删除视频
     *
     * @param ids 需要删除的视频主键
     * @return 结果
     */
    @Override
    public int deleteVideoByIds(Long[] ids) {
        return videoMapper.deleteVideoByIds(ids);
    }

    /**
     * 删除视频信息
     *
     * @param id 视频主键
     * @return 结果
     */
    @Override
    public AjaxResult deleteVideoById(Long id) {
        int i = videoMapper.deleteVideoById(id);
        if (i <= 0) {
            return AjaxResult.error("系统异常");
        }
        return AjaxResult.success();
    }

    @Override
    public void addViewsNumber(AudienceDTO audienceDTO) {
        String videoId = audienceDTO.getVideoId();
        String userId = audienceDTO.getUserId().toString();
        ValueOperations<String, String> opsForValue = stringRedisTemplate.opsForValue();
        ZSetOperations<String, String> opsForZSet = stringRedisTemplate.opsForZSet();
        String viewsNumberNotAddableKey = RedisVideoConstant.VIEWS_NUMBER_NOT_ADDABLE + videoId;
        //查找redis中是否有缓存
        Object o = opsForValue.get(RedisVideoConstant.VIEW_COUNTS + videoId);
        //有缓存
        if (o != null) {
            //查询redis 查看是否可以再次增加视频观看次数
            Double score = opsForZSet.score(viewsNumberNotAddableKey, userId);
            if (score == null || score < System.currentTimeMillis()) {
                //json转化为对象
                ViewCounts viewCounts = JSONUtil.toBean(o.toString(), ViewCounts.class);
                //播放量加一
                viewCounts.setViews(viewCounts.getViews() + 1);
                opsForValue.set(RedisVideoConstant.VIEW_COUNTS + videoId, JSONUtil.toJsonStr(viewCounts));
                //刷新缓存存活时间
                stringRedisTemplate.expire(RedisVideoConstant.VIEW_COUNTS + videoId, 1, TimeUnit.HOURS);
                //设置规定时间内重复观看视频无法增加播放量  超过时间则可以增加
                opsForZSet.add(viewsNumberNotAddableKey, userId, System.currentTimeMillis() + RedisVideoConstant.VIEWS_NUMBER_ADDABLE_TIME);
            } else {
                //刷新缓存存活时间
                stringRedisTemplate.expire(RedisVideoConstant.VIEW_COUNTS + videoId, 1, TimeUnit.HOURS);
            }

        } else {
            //无缓存
            Video video = videoMapper.selectVideoById(Long.parseLong(videoId));
            ViewCounts viewCounts = new ViewCounts(videoId, video.getViews());
            //播放量加一
            viewCounts.setViews(viewCounts.getViews() + 1);
            opsForValue.set(RedisVideoConstant.VIEW_COUNTS + videoId, JSONUtil.toJsonStr(viewCounts));
            //设置存活时间， 防止一直占用redis空间
            stringRedisTemplate.expire(RedisVideoConstant.VIEW_COUNTS + videoId, 1, TimeUnit.HOURS);
            opsForZSet.add(viewsNumberNotAddableKey, userId, System.currentTimeMillis() + RedisVideoConstant.VIEWS_NUMBER_ADDABLE_TIME);
        }
    }

    @Override
    public void batchUpdateVideo(List<ViewCounts> viewCounts) {
        videoMapper.batchUpdateVideo(viewCounts);

    }

    @Override
    public Video getLatestVideo(String videoId) {
        return videoMapper.getLatestVideo(videoId);
    }

    @Override
    public ResponseEntity uploadVideo(VideoUploadDTO videoUploadDTO) throws IOException, InterruptedException {
        MultipartFile file = videoUploadDTO.getFile();
        String videoId;
        //防止用户更换 上传视频 生成新的视频id
        if (videoUploadDTO.getVideoId() == null) {
            videoId = idWorker.nextId() + "";
        } else {
            videoId = videoUploadDTO.getVideoId();
        }
        String title = file.getOriginalFilename();
        title = title.split("\\.")[0];

        // io到临时文件
        Path tempFile = tempDir.resolve(videoId);
        log.info("io到临时文件：{}", tempFile);
        file.transferTo(tempFile);
        String currentDateTime = DateChangeUtil.getCurrentDateTime();
        // 尝试创建视频目录
        Path targetFolder = Files.createDirectories(Paths.get(transcodeConfig.getSource(), currentDateTime, videoId));
        log.info("创建文件夹目录：{}", targetFolder);
        String tempPath = tempFile.toString();
        String targetPath = targetFolder.toString();

        FFmpegUtils fFmpegUtils = new FFmpegUtils(videoUploadDTO.getFileType());
        // 切出封面
        if (!fFmpegUtils.screenShots(tempPath, String.join(File.separator, targetPath, "poster.jpg"), transcodeConfig.getPoster())) {
            throw new RuntimeException("封面截取异常");
        }
        String md5 = computeMD5(file.getInputStream());
        //校验视频md5
        //文件是否是重复上传
        VideoMD5 videoMD5 = videoMapper.getVideoByMD5(md5);
        VideoVO videoVO = new VideoVO();
        if (videoMD5 != null) {
            //重复上传直接返回视频地址
            videoVO.setVideoId(videoId + "");
            videoVO.setM3u8(videoMD5.getVideoPath());
            videoVO.setMd5(md5);
            videoVO.setTitle(title);
            videoVO.setPoster(String.join("/", "", currentDateTime, videoId, "poster.jpg"));
            return ResponseEntity.status(200).body(AjaxResult.success(videoVO));
        }
        // 封装结果
        videoVO.setVideoId(videoId);
        String videoPath = String.join("/", "", currentDateTime, videoId, "index.m3u8");
        videoVO.setPoster(String.join("/", "", currentDateTime, videoId, "poster.jpg"));
        videoVO.setM3u8(videoPath);
        videoVO.setTitle(title);
        videoVO.setMd5(md5);
        Map<String, Object> result = new HashMap<>();
        result.put("code", 200);
        result.put("data", videoVO);
        //将MD5保存在数据在数据库中防止相同文件重复上传
        videoMapper.insertVideoMD5(videoPath, md5, videoId);
        return ResponseEntity.status(200).body(result);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean publishVideoByPublishTime(LocalDateTime now) {
        List<String> videoIds = videoMapper.selectVideoByPublishTime(now);
        videoMapper.batchPublishVideo(videoIds);
        return true;

    }

    @Override
    public ResponseEntity uploadImage(ImageUploadDTO imageUploadDTO) {
        String uploadPath = transcodeConfig.getSource() + DateChangeUtil.getCurrentDateTime() + "/" + imageUploadDTO.getVideoId();
        String uploadFileName = "poster.jpg";
        MultipartFile multiFile = imageUploadDTO.getFile();
        //构建文件对象
        File file = new File(uploadPath);
        //文件目录不存在则递归创建目录
        if (!file.exists()) {
            boolean mkdirs = file.mkdirs();
            if (!mkdirs) {
                log.error("创建文件夹异常");
                HashMap<String, Object> map = new HashMap<>();
                map.put("message", "上传失败，网络异常");
                return ResponseEntity.status(500).body(map);
            }
        }
        InputStream ins = null;
        FileOutputStream outs = null;
        try {
            //获取文件输入流
            ins = multiFile.getInputStream();
            //构建文件输出流
            outs = new FileOutputStream(uploadPath + "\\" + uploadFileName);
            int len;
            byte[] bytes = new byte[1024];
            //读取一个bytes的文件内容
            while ((len = ins.read(bytes)) != -1) {
                outs.write(bytes, 0, len);
            }
            outs.close();

            HashMap<String, Object> map = new HashMap<>();
            map.put("message", "上传成功");
            return ResponseEntity.status(200).body(map);

        } catch (IOException e) {
            log.error("文件上传异常");
            e.printStackTrace();
        } finally {
            try {
                if (outs != null) {
                    outs.close();
                }
                if (ins != null) {
                    ins.close();
                }
            } catch (IOException e) {
                log.error("关闭流异常");
                e.printStackTrace();
            }
        }
        HashMap<String, Object> map = new HashMap<>();
        map.put("message", "上传失败，网络异常");
        return ResponseEntity.status(500).body(map);
    }

    @Override
    public AjaxResult deleteTempVideoById(DeleteTempFileDTO deleteTempFileDTO) {
        //用户提交上传 清除缓存文件
        List<String> videoIds = deleteTempFileDTO.getVideoIds();
        List<String> images = deleteTempFileDTO.getImages();
        for (String image : images) {
            Path tempPath = Paths.get(String.join("\\", transcodeConfig.getSource(), image));
            File file = new File(tempPath.toString());
            if (!file.exists()) {
                log.error("文件删除失败,请检查文件是否存在以及文件路径是否正确");
                return AjaxResult.error("系统异常");
            }
            file.delete();
        }
        for (String videoId : videoIds) {
            Path tempPath = Paths.get(String.join("\\", transcodeConfig.getSource(), DateChangeUtil.getCurrentDateTime(), videoId));
            File file = new File(tempPath.toString());
            if (!file.exists()) {
                log.error("文件删除失败,请检查文件是否存在以及文件路径是否正确");
                return AjaxResult.error("系统异常");
            }
            file.delete();
            Path tempPath1 = Paths.get(String.join("\\", tempDir.toString(), videoId));
            File file1 = new File(tempPath1.toString());
            if (!file1.exists()) {
                log.error("文件删除失败,请检查文件是否存在以及文件路径是否正确");
                return AjaxResult.error("系统异常");
            }
            file1.delete();
            videoMapper.deleteVideoMD5(Long.parseLong(videoId));
        }
        //判断文件不为null或文件目录存在
        return AjaxResult.success();

    }


    private Long getViewsByVideoId(String videoId) {
        //从缓存中获取视频播放量数据
        ValueOperations<String, String> forValue = stringRedisTemplate.opsForValue();
        String json = forValue.get(RedisVideoConstant.VIEW_COUNTS + videoId);
        if (json == null || json.isEmpty()) {
            return -1L;
        }
        return JSONUtil.toBean(json, ViewCounts.class).getViews();
    }

    private String computeMD5(InputStream file) {
        DigestInputStream din = null;
        try {
            MessageDigest md5 = MessageDigest.getInstance("MD5");
            //第一个参数是一个输入流
            din = new DigestInputStream(new BufferedInputStream(file), md5);
            byte[] b = new byte[1024];
            while (din.read(b) != -1) ;
            byte[] digest = md5.digest();
            return DatatypeConverter.printHexBinary(digest);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (din != null) {
                    din.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}
